# system
import logging
import pickle
import StringIO
import time

# appengine
from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template


# local
import base

class AdminPage(webapp.RequestHandler):
  def get(self):
    template_values = base.GetPersonsPaginationTemplate(self, 10)

    # show snapshots
    snapshots = base.Snapshot().all().order('-creation_time')
    template_values['snapshots'] = snapshots
   
    path =base.GetTemplatePath('admin.html')
    self.response.out.write(template.render(path, template_values))

class SetSnapshot(webapp.RequestHandler):
  def post(self):
    # security check
    if not users.is_current_user_admin():
      self.error(403)
      return
    if self.request.get('new'):
      self.NewSnapshot()
    elif self.request.get('live'):
      self.SetLiveSnapshot()
    elif self.request.get('delete'):
      self.DeleteSnapshot()
    else:
      self.error(404)

  def NewSnapshot(self):
    plist = base.PersonList()
    count = 0
    for p in base.Person.all():
      plist.list.append(p.key())
      count += 1
      if count % 100 == 0:
        logging.error(" -- dumped %d " % count);
    plist.put()
    self.redirect('/admin')

  def NewSnapshot2(self):
    # Check if we have a snapshot in progress
    results = base.PersonList().all()
    if results:
      plist = results[0]

    persons = []
    for p in db.get(plist.list):
      persons.append(p);

    # pickle into binary data
    buffer = StringIO.StringIO()
    logging.error("--- Dumping %s entires" % len(persons))
    pickle.dump(persons, buffer)
    data = buffer.getvalue()
  
    snapshot = base.Snapshot()
    snapshot.snapshot = data
    snapshot.live = False
    snapshot.state = 'done'
    snapshot.num_entries = len(persons)
    snapshot.put()
    buffer.close()
    self.redirect('/admin')

  def NewSnapshot_old(self):
    # Check if we have a snapshot in progress
    results = base.Snapshot().all().filter('state =', 'in_progress').order('creation_time').fetch(1)
    snapshot = None
    if results:
      snapshot = results[0]
      start = snapshot.num_entries
      # get the last stored persons
      buffer = StringIO.StringIO(snapshot.snapshot)
      persons = pickle.load(buffer)
      buffer.close()
    else: 
      persons = []
      start = 0

    # fetch all person. We need to break up into multiple sessions
    # because we get deadline exceeded errors if snapshot all at once.
    limit = 100
    num_results = limit
    start_time = time.time()
    while num_results == limit and time.time() - start_time < 4:
      logging.error("--- Fetching %s start %s" % (limit, start))
      #results = base.Person().all().order('-last_update').fetch(limit, start)
      num_results = 0
      start += limit
      for p in base.Person().all():
        persons.append(p)
        num_results += 1
 
    if num_results == limit:
      state = 'in_progress'
    else:
      state = 'done'

    # pickle into binary data
    buffer = StringIO.StringIO()
    logging.error("--- Dumping %s entires" % len(persons))
    pickle.dump(persons, buffer)
    data = buffer.getvalue()
  
    # store snapshot. Create a new one if not already in progress
    if not snapshot:
      snapshot = base.Snapshot()
    snapshot.snapshot = data
    snapshot.live = False
    snapshot.state = state
    snapshot.num_entries = len(persons)

    snapshot.put()
    buffer.close()
    self.redirect('/admin')

  def SetLiveSnapshot(self):
    key = self.request.params.get('snapshot')
    if not key:
      self.redirect('/admin')
      return

    # invalid old live snapshots
    live_snapshots = base.Snapshot().all().filter('live =', True)
    for s in live_snapshots:
      s.live = False
      s.put()
    
    # Set new live snapshot
    k = db.Key(key)
    snapshot = db.get(k)
    snapshot.live = True
    snapshot.put()
    self.redirect('/admin')

  def DeleteSnapshot(self):
    key = self.request.params.get('snapshot')
    logging.error("KEY: %s" % key)
    if not key:
      self.redirect('/admin')
      return
    k = db.Key(key)
    db.delete(db.get(k))
    self.redirect('/admin')

class Insert(webapp.RequestHandler):
  def post(self):
    # security check
    if not users.is_current_user_admin():
      self.error(403)
      return
    if not self.request.get('name'):
      self.redirect('/admin')
      return
    person = base.Person() 
    person.name = self.request.get('name')
    person.sex = self.request.get('sex')
    person.age = self.request.get('age')
    person.contact = self.request.get('contact')
    person.address = self.request.get('address')
    person.unit = self.request.get('unit')
    person.status = self.request.get('status')
    person.other = self.request.get('other')
    person.hospital = self.request.get('hospital')
    person.section = self.request.get('section')
    person.hospital_contact = self.request.get('hospital_contact')
    person.source = self.request.get('source')
    person.put()
    self.redirect('/admin')

class Delete(webapp.RequestHandler):
  def get(self):
    if self.request.get('all'):
      count = 0
      while True:
        for p in base.Person().all():
          p.delete()
          count += 1
          if count % 50 == 0:
            logging.error("Deleted %s" % count)
  
  def post(self):
    # security check
    if not users.is_current_user_admin():
      self.error(403)
      return

    keys = self.request.params.getall('delete')
    for key in keys:
      k = db.Key(key)
      db.delete(db.get(k))
    self.redirect('/admin')
